/*
 * @Author: 0x9DEFA478
 * @Date: 2025-08-03 19:44:39
 * @LastEditTime: 2025-08-18 20:00:18
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#ifndef hHMakeDependencyItem_Instance_HPP_
#define hHMakeDependencyItem_Instance_HPP_
#include <vector>
#include <string>
#include <sstream>
#include <list>
#include "HMakeDependencyChain.hpp"
#include "HMakeLog.hpp"
#include "HMakeValue.hpp"
#include "Tree/H_Tree_RedBlack.hpp"
#include "Utility/H_Path.hpp"




namespace HMake{

  /**
   * @brief 具有目标生成文件/文件夹的任务抽象
   */
  class DependencyItem_TargetPath:public DependencyChain::Item{
    public:
      DependencyItem_TargetPath(const std::string& TargetPath)noexcept;
      ~DependencyItem_TargetPath()noexcept;

      const std::string& TargetPath()const{return targetPath;}

      virtual std::pair<bool,uint64_t> TargetStatus()override;

    protected:
      const std::string targetPath;
  };

  /**
   * @brief 标记任务, 用于更新某个文件的更新时间(文件内容的变化不做保证)
   */
  class DependencyItem_Mark:public DependencyItem_TargetPath{
    public:
      template<typename... T_Arg>
      static Pointer New(T_Arg&&... Args){
        return Pointer(new DependencyItem_Mark(std::forward<T_Arg>(Args)...));
      }

    public:
      DependencyItem_Mark(const std::string& TargetPath,Log::Pointer log)noexcept;
      ~DependencyItem_Mark()noexcept;

      virtual int Run()override;
      virtual void DoneEvent(bool IsUpdate)override;

    private:
      Log::Pointer log;

  };

  /**
   * @brief 输入任务, 用于代表输入文件, 不进行任何生成操作, 该任务不应该依赖其他任务
   */
  class DependencyItem_Input:public DependencyItem_TargetPath{
    public:
      template<typename... T_Arg>
      static Pointer New(T_Arg&&... Args){
        return Pointer(new DependencyItem_Input(std::forward<T_Arg>(Args)...));
      }

    public:
      DependencyItem_Input(const std::string& TargetPath)noexcept;
      ~DependencyItem_Input()noexcept;

      virtual int Run()override;
      virtual void DoneEvent(bool IsUpdate)override;
      virtual std::pair<bool,uint64_t> TargetStatus()override;

  };

  /**
   * @brief 进程任务, 用于在需要的时候执行指定命令, 以生成文件; 任务可以为程序或者进程
   */
  class DependencyItem_SystemProcess:public DependencyItem_TargetPath{
    public:
      template<typename... T_Arg>
      static Pointer New(T_Arg&&... Args){
        return Pointer(new DependencyItem_SystemProcess(std::forward<T_Arg>(Args)...));
      }

      class Task{
        public:
          using Pointer=H::PointerShare<Task>;
        public:
          Task()=default;
          virtual ~Task()=default;

          virtual int Run(std::stringstream& SS,bool ioexclusive)=0;
      };

      class Task_Thread:public Task{
        public:
          template<typename... T_Arg>
          static Pointer New(T_Arg&&... Args){
            return Pointer(new Task_Thread(std::forward<T_Arg>(Args)...));
          }

          using CallType_t=std::function<int (std::stringstream&,bool)>;

        public:
          template<typename T_CallType=CallType_t>
          Task_Thread(CallType_t&& threadCall):threadCall(threadCall){}
          ~Task_Thread();

          virtual int Run(std::stringstream& SS,bool ioexclusive)override;

        private:
          CallType_t threadCall;
      };

      class Task_Process:public Task{
        public:
          template<typename... T_Arg>
          static Pointer New(T_Arg&&... Args){
            return Pointer(new Task_Process(std::forward<T_Arg>(Args)...));
          }

          enum class IOEncoding{
            UTF8,
            Local,
            LocalSystem
          };

        public:
          Task_Process(const std::list<std::string>& Args,IOEncoding io_encoding);
          ~Task_Process();

          virtual int Run(std::stringstream& SS,bool ioexclusive)override;

          static IOEncoding StringToIOEncoding(const std::string& str);

        private:
          const std::list<std::string> args;
          IOEncoding io_encoding;
      };

    public:
      DependencyItem_SystemProcess(const std::string& TargetPath,const std::list<std::string>& Args,Task_Process::IOEncoding io_encoding,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept;
      DependencyItem_SystemProcess(const std::string& TargetPath,const Task::Pointer& Task,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept;
      DependencyItem_SystemProcess(const std::string& TargetPath,const std::list<Task::Pointer>& TaskList,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept;
      ~DependencyItem_SystemProcess()noexcept;

      virtual int Run()override;
      virtual void DoneEvent(bool IsUpdate)override;

    private:
      std::list<Task::Pointer> taskList;
      const std::string runLog;
      const std::string skipLog;
      Log::Pointer log;

  };

  /**
   * @brief 命令行任务 不生成文件, 初始状态总是认为生成未完成, 执行成功后认为生成完成
   */
  class DependencyItem_Command:public DependencyItem_SystemProcess{
    public:
      template<typename... T_Arg>
      static Pointer New(T_Arg&&... Args){
        return Pointer(new DependencyItem_Command(std::forward<T_Arg>(Args)...));
      }

    public:
      DependencyItem_Command(const std::list<std::string>& Args,Task_Process::IOEncoding io_encoding,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept;
      DependencyItem_Command(const Task::Pointer& Task,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept;
      DependencyItem_Command(const std::list<Task::Pointer>& TaskList,const std::string& RunLog,const std::string& SkipLog,Log::Pointer log)noexcept;
      ~DependencyItem_Command()noexcept;

      virtual int Run()override;
      virtual std::pair<bool,uint64_t> TargetStatus()override;

    private:
      bool isRun;
  };

  /**
   * @brief 创建文件夹任务, 用于在需要的时候创建文件夹
   */
  class DependencyItem_Directory:public DependencyItem_TargetPath{
    public:
      template<typename... T_Arg>
      static Pointer New(T_Arg&&... Args){
        return Pointer(new DependencyItem_Directory(std::forward<T_Arg>(Args)...));
      }

      using LockPointer=H::PointerShare<H::Lock>;

      class Collection{
        public:
          using Pointer=H::PointerShare<Collection>;

        public:
          Collection();

          DependencyChain::Item::Pointer Insert(const H::Path& path,const std::string& RunLog,const std::string& SkipLog,Log::Pointer& log);

        private:
          H::Tree::RedBlack<H::Path,DependencyChain::Item::Pointer> taskMap;
          const LockPointer lock;
      };

    public:
      DependencyItem_Directory(const std::string& TargetPath,const std::string& RunLog,const std::string& SkipLog,Log::Pointer& log,const LockPointer& lock=LockPointer())noexcept;
      ~DependencyItem_Directory()noexcept;

      virtual int Run()override;
      virtual void DoneEvent(bool IsUpdate)override;
      virtual std::pair<bool,uint64_t> TargetStatus()override;

    private:
      const std::string runLog;
      const std::string skipLog;
      Log::Pointer log;
      const LockPointer lock;

  };

}




#endif //hHMakeDependencyItem_Instance_HPP_
